#include <xeroskernel.h>

/*
    signal trampoline
*/
void sigtramp(void (*handler)(void *), void *cntx, void *osp) {
	handler(cntx);
	sigreturn(osp);
}

/*
	Register signal handler
*/
int installHandler(pcb *p, int sig, void (*newHandler)(void *), void (** oldHandler)(void *) ){
	//invalid check
    if(sig > 31 || sig < 0) return -1;

    //invalid address
    if(newHandler == 0) return -2;

    //preserve old handler and set new one
	kprintf("newHandler %x ",newHandler);
	kprintf("oldHandler %x\n",oldHandler);
	kprintf("p->sigtable[sig] %x\n", p->sigtable[sig]);
	*oldHandler = p->sigtable[sig];
    p->sigtable[sig] = newHandler;

    //change valid bit mask
    p->validmask |= (1 << (sig));

    return 0;
}

/*
	Send signal to pid
*/
int signal(int pid, int sig) {
    
    pcb *p;
    int pi = -1;
    pi = getPCBi(pid);

    //check valid pid
    if (pi == -1) return -18;

    //get PCB
    p = &proctab[pi];

    //check signal validity
    if (( p->validmask & (1 << sig) ) == 0) return -3;

    //wake up blocked processes
    if(p->state == STATE_BLOCKED) ready(p);

    //put in pending
    p->acceptedmask = p->acceptedmask | (1 << sig);
    
    //check if need to be signaled now
    if(isLargestBit(p) ) {
    	context_frame *cf;
    	//deliver now
        cf = p->esp;
	    cf--;
	    memset(cf, 0x81, sizeof( context_frame ) );
	    
	    cf->iret_cs = getCS();
	    cf->iret_eip = (unsigned int)sigtramp;
	    cf->eflags = STARTING_EFLAGS;
	    cf->esp = (int)(cf + 1);
	    cf->ebp = cf->esp;
	    cf->stackSlots[1] = p->sigtable[sig];
	    cf->stackSlots[2] = (unsigned int)(&cf);
	    cf->stackSlots[3] = p->esp;
	    p->esp = (int)cf;

        //change pendingmask
        p->pendingmask = p->pendingmask | (1 << sig);
    	
    } 
	return 0;
}

